/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package searchviewer;

import hk.polyu.*;

import java.io.*;
import java.util.AbstractMap.SimpleEntry;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;

public class SearchViewer extends Application {

	File file;
	WebView view;
	WebEngine eng;
	VBox box1;

	@Override
	public void start(Stage primaryStage) throws Exception {
		Pane root = new WebViewPane();
		primaryStage.setScene(new Scene(root, 1024, 768));
		primaryStage.setTitle("Wikipedia Crawler and Search Engine");
		primaryStage.show();
	}

	/**
	 * The main() method is ignored in correctly deployed JavaFX application.
	 * 
	 * @param args
	 *            the command line arguments
	 */
	public static void main(String[] args) {
		launch(args);
	}

	/**
	 * Create a resizable WebView pane
	 */
	public class WebViewPane extends Pane {
		
		protected void addTree(Tree<SimpleEntry<String, Integer>> root, TreeItem<String> rootItem) {

			for (Tree<SimpleEntry<String, Integer>> child : root.getSubTrees()) {
				String name = WikiCrawler.nameFromUrl(child.getHead().getKey());
				TreeItem<String> it = new TreeItem<String>(name);
				rootItem.getChildren().add(it);
				
				// recursive.
				addTree(child, it);
			}
		}
		

		public WebViewPane() {
			VBox.setVgrow(this, Priority.ALWAYS);
			setMaxWidth(Double.MAX_VALUE);
			setMaxHeight(Double.MAX_VALUE);

			view = new WebView();
			view.setMinSize(200, 200);
			view.setPrefSize(200, 200);
			eng = view.getEngine();

			final URL urlHello = getClass().getResource("search.html");
			eng.load(urlHello.toExternalForm());

			final Label labelFile = new Label(
					"Please select a local directory to store crawled files");

			final Button goButton = new Button("Search");
			goButton.setDisable(true);

			final Button crawlBtn = new Button("Crawl The Web!!");
			crawlBtn.setDisable(true);
			
			Button btn = new Button("Select Directory");
			
			final TextField initUrlField = new TextField(
					"http://en.wikipedia.org/wiki/Category:IPad");
			initUrlField.setMaxHeight(Double.MAX_VALUE);
			
			final TextField searchField = new TextField("");
			searchField.setMaxHeight(Double.MAX_VALUE);
			
	        final TreeView<String> treeView = new TreeView<String> ();
	        treeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
	        treeView.getSelectionModel().selectedItemProperty().addListener(
	        		new ChangeListener<Object>() {

						@Override
						public void changed(
								ObservableValue<?> arg0,
								Object arg1, Object arg2) {
							TreeItem<String> treeItem = (TreeItem<String>)arg2;
			                System.out.println("Selected item is " + treeItem.getValue());
			                
			                // Open text.
			                String FilePath = labelFile.getText();
			                if (! FilePath.endsWith(File.separator))
			                		FilePath += File.separator;
			                FilePath += treeItem.getValue() + ".html";
			                File file = new File(FilePath);
							String text = readFile(file);
							eng.loadContent(text);
							
						}
	        	
			});
	        
			
			crawlBtn.setOnAction(new EventHandler<ActionEvent>() {

				@Override
				public void handle(ActionEvent arg0) {
					
					searchField.setText("Initializing...");
					// First, crawl the web.
					String u = initUrlField.getText().trim();
					String p = labelFile.getText().trim();
					final WikiCrawler wc = new WikiCrawler(u, p);
					
					wc.setOnCrawlListener(new WikiCrawler.OnCrawlListener() {
						
						@Override
						public void onPageCrawled(SimpleEntry<String, Integer> item) {
							
							final String notice = String.format(
									"Fetching %s at level %d\r\n", item.getKey(), item.getValue());
							System.out.println(notice);
							// async task.
							Platform.runLater(new Runnable() {
								@Override
								public void run() {
									searchField.setText(notice);
								}
							});
							
						}

						@Override
						public void onCrawlComplete() {
							// async task.
							Platform.runLater(new Runnable() {
								@Override
								public void run() {
									searchField.setText("Web Crawl Complete! Building Index");
									
									// Add tree view.
									Tree<SimpleEntry<String, Integer>> dtree = wc.getTree();
									String rootNode = WikiCrawler.nameFromUrl(dtree.getHead().getKey());
									TreeItem<String> itroot = new TreeItem<String>(rootNode);
									addTree(dtree, itroot);
									treeView.setRoot(itroot);
									itroot.setExpanded(true);
									
									// Build Index
									BuildIndex(labelFile.getText(), null);
									goButton.setDisable(false);
									searchField.setText("Build Index Complete. Enter Search String here.");
									searchField.selectAll();
									searchField.requestFocus();
								}
							});
						}
					});
					
					// Crawl the web.
					wc.crawl();
				}
			});

			btn.setOnAction(new EventHandler<ActionEvent>() {
				@Override
				public void handle(ActionEvent event) {
					DirectoryChooser directoryChooser = new DirectoryChooser();

					directoryChooser.setTitle("This is my file choose");

					// Show open file dialog
					File defaultDirectory = new File(System.getProperty(
							"user.dir").toString());
					directoryChooser.setInitialDirectory(defaultDirectory);

					File file = directoryChooser.showDialog(null);

					if (file != null) {
						labelFile.setText(file.getPath());
						crawlBtn.setDisable(false);
					}
				}
			});


			EventHandler<ActionEvent> goAction = new EventHandler<ActionEvent>() {
				@Override
				public void handle(ActionEvent event) {
					box1.getChildren().clear();
					Search(labelFile.getText(), searchField.getText());
				}
			};
			goButton.setOnAction(goAction);
			searchField.setOnAction(goAction);

			box1 = new VBox(1);

			ScrollPane sp = new ScrollPane();
			sp.setVmax(540);
			sp.setPrefSize(350, 350);
			sp.setContent(box1);

			GridPane grid = new GridPane();
			grid.setVgap(5);
			grid.setHgap(5);
			
			GridPane.setConstraints(labelFile, 0, 1, 1, 1, HPos.CENTER,
					VPos.CENTER, Priority.ALWAYS, Priority.SOMETIMES);
			GridPane.setConstraints(crawlBtn, 1, 2);
			
			GridPane.setConstraints(btn, 1, 1);
			
			GridPane.setConstraints(searchField, 0, 3, 1, 1, HPos.CENTER,
					VPos.CENTER, Priority.ALWAYS, Priority.SOMETIMES);
			GridPane.setConstraints(goButton, 1, 3);
			
			GridPane.setConstraints(sp, 1, 4, 2, 1, HPos.CENTER, VPos.CENTER,
					Priority.ALWAYS, Priority.ALWAYS);
			GridPane.setConstraints(treeView, 0, 4);
			
			GridPane.setConstraints(view, 0, 5, 2, 1, HPos.CENTER, VPos.CENTER,
					Priority.ALWAYS, Priority.ALWAYS);
			grid.getColumnConstraints().addAll(
					new ColumnConstraints(50, 70, Double.MAX_VALUE,
							Priority.ALWAYS, HPos.CENTER, true),
					new ColumnConstraints(130, 70, 40, Priority.NEVER,
							HPos.CENTER, true));

			grid.getChildren().addAll(initUrlField, labelFile, crawlBtn, btn,
					treeView, searchField, goButton, sp, view);

			getChildren().add(grid);
		}

		public String Search(String path, String query) {
			String Reason = "";
			String indexPath = System.getProperty("user.dir").toString() + File.separator;
			DocumentIndex di = new DocumentIndex();
			InvertedIndex ii = new InvertedIndex();

			try {
				di.load(indexPath + DocumentIndex.FILE_NAME);
				ii.load(indexPath + InvertedIndex.FILE_NAME);
			} catch (IOException e) {
				e.printStackTrace();
			}

			Searcher q = new Searcher(ii, di);

			// "\'data transmission' AND \'Data Compression\' OR communication"

			Vector<QueryResult> finalResult = q.query(query);

			Iterator<QueryResult> it = finalResult.iterator();
			int row = 0;
			GridPane gridpane = new GridPane();
			gridpane.setVgap(5);
			gridpane.setHgap(5);
			while (it.hasNext()) {
				QueryResult r = it.next();

				final String FilePath = path + File.separator + r.mName;

				final Label labelFileName = new Label();

				final Label labelFileWeight = new Label();

				labelFileName.setText(r.mName);

				labelFileWeight.setText(String.valueOf(r.mWeight));

				Button btn = new Button();
				btn.setText("Show file");
				// btn.setId(path + "/" + r.mName);
				btn.setOnAction(new EventHandler<ActionEvent>() {
					@Override
					public void handle(ActionEvent event) {

						File file = new File(FilePath);

						String text = readFile(file);
						eng.loadContent(text);
						// text =
						// text.replace("\n","<br>").replace("\"","\\\"");
					}
				});

				GridPane.setConstraints(labelFileName, 0, row, 1, 1,
						HPos.CENTER, VPos.CENTER, Priority.ALWAYS,
						Priority.SOMETIMES);
				GridPane.setConstraints(labelFileWeight, 1, row, 1, 1,
						HPos.CENTER, VPos.CENTER, Priority.ALWAYS,
						Priority.SOMETIMES);
				GridPane.setConstraints(btn, 2, row);

				gridpane.getColumnConstraints().addAll(
						new ColumnConstraints(100, 70, Double.MAX_VALUE,
								Priority.ALWAYS, HPos.CENTER, true),
						new ColumnConstraints(100, 70, Double.MAX_VALUE,
								Priority.ALWAYS, HPos.CENTER, true),
						new ColumnConstraints(130, 70, 40, Priority.NEVER,
								HPos.CENTER, true));

				gridpane.getChildren().addAll(labelFileName, labelFileWeight,
						btn);

				row++;
			}

			box1.getChildren().add(gridpane);

			return Reason;

		}

		public void BuildIndex(String path, String stopword) {
			CollectionBuilder cb = new CollectionBuilder(path);
			CollectionInfo ci = cb.build(true, stopword);

			DocumentIndex di = new DocumentIndex();
			InvertedIndex ii = new InvertedIndex();

			String indexPath = System.getProperty("user.dir").toString();

			di.generate(ci);
			ii.generate(ci);
			try {
				di.save(indexPath);
				ii.save(indexPath);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		protected void layoutChildren() {
			List<Node> managed = getManagedChildren();
			double width = getWidth();
			double height = getHeight();
			double top = getInsets().getTop();
			double right = getInsets().getRight();
			double left = getInsets().getLeft();
			double bottom = getInsets().getBottom();
			for (int i = 0; i < managed.size(); i++) {
				Node child = managed.get(i);
				layoutInArea(child, left, top, width - left - right, height
						- top - bottom, 0, Insets.EMPTY, true, true,
						HPos.CENTER, VPos.CENTER);
			}
		}

		private String readFile(File file) {
			StringBuilder stringBuffer = new StringBuilder();
			BufferedReader bufferedReader = null;

			try {

				bufferedReader = new BufferedReader(new FileReader(file));

				String text;
				while ((text = bufferedReader.readLine()) != null) {
					stringBuffer.append(text);
				}

			} catch (FileNotFoundException ex) {
				Logger.getLogger(SearchViewer.class.getName()).log(
						Level.SEVERE, null, ex);
			} catch (IOException ex) {
				Logger.getLogger(SearchViewer.class.getName()).log(
						Level.SEVERE, null, ex);
			} finally {
				try {
					bufferedReader.close();
				} catch (IOException ex) {
					Logger.getLogger(SearchViewer.class.getName()).log(
							Level.SEVERE, null, ex);
				}
			}

			return stringBuffer.toString();
		}
	}
}
